/* Copyright 2007-2008 dnAnalytics Project.
 *
 * Contributors to this file:
 * Patrick van der Velde
 * Marcus Cuda - http://marcus.cuda.net
 *
 * This file is part of dnAnalytics.  dnAnalytics is licensed under the 
 * Microsoft Public License. See License.txt for a complete copy of the
 * license.
 */

using System;
using dnAnalytics.Math;
using dnAnalytics.Properties;

namespace dnAnalytics.LinearAlgebra
{
    public partial class DenseVector
    {
        /// <summary>Computes the dot product of this vector with another.</summary>
        /// <param name="other">The vector to compute the dot product with.</param>
        /// <returns>The dot product of this vector and other.</returns>
        /// <exception cref="ArgumentNullException">If the other vector is <see langword="null" />.</exception>
        /// <exception cref="NotConformableException">If this vector  and other are not the same size.</exception>
        public override double DotProduct(Vector other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }

            if (Count != other.Count)
            {
                throw new NotConformableException("other", Resources.ParameterNotConformable);
            }

            DenseVector otherVector = other as DenseVector;
            if (otherVector == null)
            {
                return base.DotProduct(other);
            }

            double result = 0;
            for (int i = 0; i < mData.Length; i++)
            {
                result += mData[i]*otherVector.mData[i];
            }
            return result;
        }

        /// <summary>
        /// Adds another vector to this vector.
        /// </summary>
        /// <param name="other">The vector to add to this one.</param>
        /// <exception cref="ArgumentNullException">If the other vector is <see langword="null" />.</exception> 
        /// <exception cref="NotConformableException">If this vector and <paramref name="other"/> are not the same size.</exception>
        public override void Add(Vector other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (Count != other.Count)
            {
                throw new NotConformableException("other", Resources.ParameterNotConformable);
            }

            DenseVector otherVector = other as DenseVector;
            if (otherVector == null)
            {
                base.Add(other);
            }
            else
            {
                for (int i = 0; i < mData.Length; i++)
                {
                    mData[i] += otherVector.mData[i];
                }
            }
        }

        /// <summary>
        /// Pointwise multiplies this vector with another vector.
        /// </summary>
        /// <param name="other">The vector to pointwise multiply with this one.</param>
        /// <exception cref="ArgumentNullException">If the other vector is <see langword="null" />.</exception> 
        /// <exception cref="NotConformableException">If this vector and <paramref name="other"/> are not the same size.</exception>
        /// <returns>A new vector that is the pointwise multiplication of this vector and <paramref name="other"/>.</returns>
        public override Vector PointwiseMultiply(Vector other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (Count != other.Count)
            {
                throw new NotConformableException("other", Resources.ParameterNotConformable);
            }

            DenseVector otherVector = other as DenseVector;
            if (otherVector == null)
            {
                return base.PointwiseMultiply(other);
            }
            Vector result = Clone();
            for (int i = 0; i < mData.Length; i++)
            {
                result[i] = mData[i]*otherVector.mData[i];
            }
            return result;
        }


        /// <summary>
        /// Subtracts another vector from this vector.
        /// </summary>
        /// <param name="other">The vector to subtract from this one.</param>
        /// <exception cref="ArgumentNullException">If the other vector is <see langword="null" />.</exception> 
        /// <exception cref="NotConformableException">If this vector and <paramref name="other"/> are not the same size.</exception>
        public override void Subtract(Vector other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (Count != other.Count)
            {
                throw new NotConformableException("other", Resources.ParameterNotConformable);
            }
            DenseVector otherVector = other as DenseVector;
            if (otherVector == null)
            {
                base.Subtract(other);
            }
            else
            {
                for (int i = 0; i < mData.Length; i++)
                {
                    mData[i] -= otherVector.mData[i];
                }
            }
        }

        /// <summary>
        /// Multiplies this vector by scalar.
        /// </summary>
        /// <param name="scalar">The scalar to multiply this vector with.</param>
        public override void Multiply(double scalar)
        {
            if (FloatingPointUtilities.EqualsWithinSignificantFigures(1.0, scalar, 15))
            {
                return;
            }
            for (int i = 0; i < mData.Length; i++)
            {
                mData[i] *= scalar;
            }
        }
    }
}